package com.cz.udpsendermaster;

import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

/**
 * @author 陈章
 * create at 2021/1/19 14:14
 * desc:Udp发送端核心类
 */
public class UdpSender {
    private static final String TAG = "UdpSender";
    private final Handler childHandler;
    private OnSenderStatusListener onSenderStatusListener;
    private final int MSG_TYPE_START = 10;
    private final int MSG_TYPE_SEND_STRING = 20;
    private final int MSG_TYPE_SEND_BYTE = 30;
    private final int MSG_TYPE_RELEASE = 40;
    private ReceiverWrapper receiverWrapper;

    /**
     * 该callback运行于子线程
     */
    private class ChildCallback implements Handler.Callback {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_TYPE_START:
                    ReceiverModel receiverModel = (ReceiverModel) msg.obj;
                    try {
                        receiverWrapper = new ReceiverWrapper(receiverModel);
                    } catch (SocketException e) {
                        e.printStackTrace();
                    }
                    break;
                case MSG_TYPE_SEND_STRING:
                    String value = (String) msg.obj;
                    try {
                        receiverWrapper.send(value);
                    } catch (IOException e) {
                        e.printStackTrace();
                        callbackSendMsgFailure(e);
                    }
                    break;
                case MSG_TYPE_SEND_BYTE:
                    byte[] value2 = (byte[]) msg.obj;
                    try {
                        receiverWrapper.send(value2);
                    } catch (IOException e) {
                        e.printStackTrace();
                        callbackSendMsgFailure(e);
                    }
                    break;
                case MSG_TYPE_RELEASE:
                    //关闭Handler轮循
                    childHandler.removeCallbacksAndMessages(null);
                    childHandler.getLooper().quit();
                    break;
            }
            return false;
        }
    }

    private class ReceiverModel {
        public String receiverIp;
        public int receiverPort;

        public ReceiverModel(String serverIp, int serverPort) {
            this.receiverIp = serverIp;
            this.receiverPort = serverPort;
        }
    }

    /**
     * 接收者封装
     */
    private class ReceiverWrapper {
        private ReceiverModel receiverModel;
        private DatagramSocket datagramSocket;

        public ReceiverWrapper(ReceiverModel receiverModel) throws SocketException {
            this.receiverModel = receiverModel;
            initReceiver();
        }

        private void initReceiver() throws SocketException {
            datagramSocket = new DatagramSocket();
        }

        public void send(String value) throws IOException {
            send(value.getBytes(java.nio.charset.StandardCharsets.UTF_8));
        }

        public void send(byte[] value) throws IOException {
            //2. 创建一个DatagramPack包用于创建发送的数据
            DatagramPacket datagramPacket = new DatagramPacket(value, value.length, InetAddress.getByName(receiverModel.receiverIp), receiverModel.receiverPort);
            //3. 发送数据
            datagramSocket.send(datagramPacket);
        }
    }

    public UdpSender(String serverIp, int serverPort) {
        HandlerThread handlerThread = new HandlerThread("udp sender " + this);
        handlerThread.start();
        //子线程Handler
        childHandler = new Handler(handlerThread.getLooper(), new ChildCallback());

        ReceiverModel receiverModel = new ReceiverModel(serverIp, serverPort);
        childHandler.obtainMessage(MSG_TYPE_START, receiverModel).sendToTarget();
    }

    public void send(String data) {
        childHandler.obtainMessage(MSG_TYPE_SEND_STRING, data).sendToTarget();
    }

    public void send(byte[] data) {
        childHandler.obtainMessage(MSG_TYPE_SEND_BYTE, data).sendToTarget();
    }

    public void release() {
        childHandler.obtainMessage(MSG_TYPE_RELEASE).sendToTarget();
    }

    public void setOnSenderStatusListener(OnSenderStatusListener onSenderStatusListener) {
        this.onSenderStatusListener = onSenderStatusListener;
    }

    private void callbackSendMsgFailure(IOException e) {
        if (onSenderStatusListener != null) {
            onSenderStatusListener.onSendMsgFailure(e);
        }
    }

    private void callbackError(IOException e) {
        if (onSenderStatusListener != null) {
            onSenderStatusListener.onError(e);
        }
    }

    public interface OnSenderStatusListener {
        /**
         * 其它异常
         * @param e
         */
        void onError(Throwable e);

        /**
         * 发送消息失败
         * @param e
         */
        void onSendMsgFailure(Throwable e);
    }

}
